/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.web.frontendproject.zerocode.operation;

import com.inspur.edp.web.common.entity.TerminalType;
import com.inspur.edp.web.common.environment.ExecuteEnvironment;
import com.inspur.edp.web.common.io.FileUtility;
import com.inspur.edp.web.frontendproject.zerocode.ZeroCodeFormParameter;
import com.inspur.edp.web.frontendproject.zerocode.ZeroCodeParameter;
import com.inspur.edp.web.frontendproject.zerocode.operation.sourcegenerate.SourceCodeManager;
import com.inspur.edp.web.frontendproject.zerocode.operation.webdevjson.WebDevJsonManager;
import com.inspur.edp.web.jitengine.JITEngineManager;
import com.inspur.edp.web.jitruntimebuild.scriptcache.api.entity.PublishScriptRequest;
import com.inspur.edp.web.jitruntimebuild.scriptcache.api.service.ScriptCacheService;
import com.inspur.edp.web.jitruntimebuild.scriptcache.localserver.LocalServerPathGenerator;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;

public class ZeroCodeManager {

    ScriptCacheService scriptCacheServiceInstance;

    private ZeroCodeManager() {
        this.scriptCacheServiceInstance = SpringBeanUtils.getBean(ScriptCacheService.class);
    }

    public static ZeroCodeManager getInstance() {
        return new ZeroCodeManager();
    }

    /**
     * 保存零代码参数元数据到webdev文件目录
     *
     * @param zeroCodeParameter
     */
    public void saveZeroCodeParameterMetadataIntoJson(ZeroCodeParameter zeroCodeParameter) {

        // 保存webdevjson文件
        WebDevJsonManager.saveWebDevJson(zeroCodeParameter);
    }

    public void build(ZeroCodeParameter zeroCodeParameter) {
        // 如果存在pc表单
        if (zeroCodeParameter.hasFormParameter(TerminalType.PC)) {
            // 执行 npm run build
            JITEngineManager.buildFrontendProject(zeroCodeParameter.getAbsoluteBasePath(), ExecuteEnvironment.Runtime, TerminalType.PC);
        }

        // 如果存在移动表单
        if (zeroCodeParameter.hasFormParameter(TerminalType.MOBILE)) {
            JITEngineManager.buildFrontendProject(zeroCodeParameter.getAbsoluteBasePath(), ExecuteEnvironment.Runtime, TerminalType.MOBILE);
        }
    }

    public void generateSource(ZeroCodeParameter zeroCodeParameter) {
        SourceCodeManager.generateSourceCode(zeroCodeParameter);

    }

    public void deploy(ZeroCodeParameter zeroCodeParameter) {
        // pc 表单
        if (zeroCodeParameter.hasFormParameter(TerminalType.PC)) {
            // 编译后的目标目录
            String distRollupPath = getAppDistRollupPath(zeroCodeParameter.getAbsoluteBasePath());

            String deployPath = FileUtility.combineOptional(zeroCodeParameter.getServerPath(), "web", zeroCodeParameter.getServiceUnitPath().toLowerCase(), "web");
            FileUtility.copyFolder(distRollupPath, deployPath);
            if (FileUtility.exists(deployPath)) {

                //version.json
                publishWithSingleFile(deployPath, zeroCodeParameter, "version.json");
                //index.html
                publishWithSingleFile(deployPath, zeroCodeParameter, "index.html");
                //polyfills.js
                publishWithSingleFile(deployPath, zeroCodeParameter, "polyfills.js");
                //main.js
                publishWithSingleFile(deployPath, zeroCodeParameter, "main.js");

                zeroCodeParameter.getFormParameters().stream().filter(t -> !t.isMobile()).forEach(t -> {
                    String strDeployPathWithProject = FileUtility.combine(deployPath, zeroCodeParameter.getProjectName().toLowerCase());
                    PublishScriptRequest publishScriptRequest = new PublishScriptRequest();
                    publishScriptRequest.setAbsoluteBaseDirectory(strDeployPathWithProject);
                    // 为了和设计时传参保持一致  将参数调整为小写形式
                    publishScriptRequest.setProjectName(zeroCodeParameter.getProjectName().toLowerCase());
                    publishScriptRequest.setFormCode(t.getCode());

                    String strLocalServerPath = LocalServerPathGenerator.getNewInstance(false).getLocalServerWebPath();
                    String strRelativePath = FileUtility.getRelativePath(strLocalServerPath, strDeployPathWithProject, true);
                    publishScriptRequest.setProjectRelativePath(strRelativePath);
                    // 无需更新元数据版本
                    //publishScriptRequest.setUpdateMetadataVersion(false);
                    // 由于零代码不存在对应的元数据 因此设置元数据为工程名称 作为一个临时参数值
                    publishScriptRequest.setMetaDataId(t.getMetadata().getHeader().getId());
                    this.scriptCacheServiceInstance.publishScriptWithSingleFileName(publishScriptRequest, t.getCode().toLowerCase(), null);
                });


            }
        }
        // 移动表单
        if (zeroCodeParameter.hasFormParameter(TerminalType.MOBILE)) {
            // 编译后的目标目录
            String distRollupPath = getMobileAppDistRollupPath(zeroCodeParameter.getAbsoluteBasePath());

            String deployPath = FileUtility.combineOptional(zeroCodeParameter.getServerPath(), "web", zeroCodeParameter.getServiceUnitPath().toLowerCase(), "mob");
            FileUtility.copyFolder(distRollupPath, deployPath);

            if (FileUtility.exists(deployPath)) {

                 zeroCodeParameter.getFormParameters().stream().filter(ZeroCodeFormParameter::isMobile).forEach((zeroCodeFormParameter)->{
                     String metaDataId = zeroCodeParameter.getProjectName().toLowerCase();
                     if (zeroCodeFormParameter != null) {
                         metaDataId = zeroCodeFormParameter.getMetadata().getHeader().getId();
                     }


                     String strDeployPathWithProject = FileUtility.combine(deployPath, zeroCodeParameter.getProjectName().toLowerCase());
                     PublishScriptRequest publishScriptRequest = new PublishScriptRequest();
                     publishScriptRequest.setAbsoluteBaseDirectory(strDeployPathWithProject);
                     // 为了和设计时传参保持一致  将参数调整为小写形式
                     publishScriptRequest.setProjectName(zeroCodeParameter.getProjectName().toLowerCase());

                     String strLocalServerPath = LocalServerPathGenerator.getNewInstance(false).getLocalServerWebPath();
                     String strRelativePath = FileUtility.getRelativePath(strLocalServerPath, strDeployPathWithProject, true);
                     publishScriptRequest.setProjectRelativePath(strRelativePath);
                     publishScriptRequest.setMetaDataId(metaDataId);
                     publishScriptRequest.setFormCode(zeroCodeFormParameter.getCode());
                     publishScriptRequest.setZeroCodeMobileForm(true);
                     // 无需更新元数据版本
                     //publishScriptRequest.setUpdateMetadataVersion(false);
                     this.scriptCacheServiceInstance.publishScriptWithDirectory(publishScriptRequest);
                 });

            }
        }

    }

    private void publishWithSingleFile(String deployPath, ZeroCodeParameter zeroCodeParameter, String fileName) {
        String strDeployPathWithProject = FileUtility.combine(deployPath, zeroCodeParameter.getProjectName().toLowerCase());
        PublishScriptRequest publishScriptRequest = new PublishScriptRequest();
        publishScriptRequest.setAbsoluteBaseDirectory(strDeployPathWithProject);
        // 为了和设计时传参保持一致  将参数调整为小写形式
        publishScriptRequest.setProjectName(zeroCodeParameter.getProjectName().toLowerCase());

        String strLocalServerPath = LocalServerPathGenerator.getNewInstance(false).getLocalServerWebPath();
        String strRelativePath = FileUtility.getRelativePath(strLocalServerPath, strDeployPathWithProject, true);
        publishScriptRequest.setProjectRelativePath(strRelativePath);
        // 无需更新元数据版本
        //publishScriptRequest.setUpdateMetadataVersion(false);
        // 由于零代码不存在对应的元数据 因此设置元数据为工程名称 作为一个临时参数值
        publishScriptRequest.setMetaDataId(zeroCodeParameter.getProjectName().toLowerCase());
        this.scriptCacheServiceInstance.publishScriptWithSingleFileName(publishScriptRequest, "", fileName);
    }


    /**
     * 获取生成文件代码的路径
     *
     * @param absolutePath
     * @return
     */
    private String getAppDistRollupPath(String absolutePath) {
        return FileUtility.getPlatformIndependentPath(FileUtility.combineOptional(absolutePath, "src", "app", "dist-rollup"));
    }

    /**
     * 获取生成文件代码的路径
     *
     * @param absolutePath
     * @return
     */
    private String getMobileAppDistRollupPath(String absolutePath) {
        return FileUtility.getPlatformIndependentPath(FileUtility.combineOptional(absolutePath, "src", "mobileapp", "dist-rollup"));
    }
}
